package darknet.application.chat.impl.net;

import darknet.application.chat.impl.net.message.SessionExitMessage;
import darknet.application.chat.impl.net.message.BroadcastExitChannelMessage;
import darknet.application.chat.impl.net.message.BroadcastChannelMessage;
import darknet.application.chat.impl.net.message.SessionStartMessage;
import darknet.application.chat.impl.net.message.ListChannelMessage;
import darknet.application.chat.impl.net.message.PrivateMessage;
import darknet.application.chat.impl.net.message.ExitChannelMessage;
import darknet.application.chat.impl.net.message.JoinChannelMessage;
import darknet.application.chat.impl.net.message.ChannelMessage;
import darknet.application.chat.impl.net.message.BroadcastJoinChannelMessage;
import darknet.application.chat.impl.net.message.CloseChannelMessage;
import darknet.core.impl.net.MessageHeaderImpl;
import darknet.core.spec.net.MessageHeader;
import darknet.core.spec.net.NetworkManager;
import darknet.core.spec.net.Node;

/**
 * Chat message factory.
 * 
 * @author Yoyo
 */
public class ChatMessageFactory {
    
    /** Header for each chat message */
    public static final MessageHeader header;

    /** Class instance */
    private static ChatMessageFactory INSTANCE;
    
    /**
     * Static initialisation block.
     */
    static {
	header = new MessageHeaderImpl(ChatProtocol.getCurrent());
    }
    
    /**
     * Get an instance of the class.
     * 
     * @param network The network manager to use
     * @return
     */
    public synchronized static ChatMessageFactory getInstance(
	    NetworkManager network) {
	
	if(INSTANCE == null) {
	    INSTANCE = new ChatMessageFactory(network);
	}
	
	return INSTANCE;
    }
    
    /** The network manager */
    private NetworkManager network;
    
    /**
     * Private constructor.
     */
    private ChatMessageFactory(NetworkManager network) {
	
	if (network == null) {
	    throw new IllegalArgumentException("network is null");
	}
	this.network = network;
    }

    /**
     * Make a new session start message.
     * 
     * @param to
     * @return
     */
    public SessionStartMessage makeSessionStartMessage(Node to) {
        return new SessionStartMessage(header, network.myNode(), to);
    }

    /**
     * Make a new private message.
     *
     * @param message The message content.
     * @param to      The receiver.
     * @return
     */
    public PrivateMessage makePrivateMessage(String message, Node to) {
	return new PrivateMessage(header, network.myNode(), to, message);
    }

    /**
     * Make a new session exit message.
     * 
     * @param to
     * @return
     */
    public SessionExitMessage makeSessionExitMessage(Node to) {
        return new SessionExitMessage(header, network.myNode(), to);
    }

    /**
     * Make a new List Channel Message.
     *
     * @param to
     * @return
     */
    public ListChannelMessage makeListChannelMessage(Node to) {
        return new ListChannelMessage(header, network.myNode(), to);
    }

    /**
     * Make a join channel message.
     *
     * @param to
     * @param channelName
     * @return
     */
    public JoinChannelMessage makeJoinChannelMessage(
            Node to, String channelName) {

        return new JoinChannelMessage(header, network.myNode(), to,channelName);
    }

    /**
     * Make a broadcast join channel message.
     * 
     * @param to
     * @param channelName
     * @param joiner
     * @return
     */
    public BroadcastJoinChannelMessage makeBroadcastJoinChannelMessage(
            Node to, String channelName, Node joiner) {

        return new BroadcastJoinChannelMessage(
                header, network.myNode(), to, channelName, joiner);
    }

    /**
     * Make a new channel message.
     *
     * @param message The message to send.
     * @param to    The node hosting the channel.
     * @param channel The channel name.
     * @return
     */
    public ChannelMessage makeChannelMessage(String message,
	    Node to, String channel) {

	return new ChannelMessage(header, network.myNode(), to, message,
                channel);
    }

    /**
     * Make a new broadcast channel message.
     *
     * @param message
     * @param to
     * @param channel
     * @param originalPoster
     * @return
     */
    public BroadcastChannelMessage makeBroadcastChannelMessage(String message,
	    Node to, String channel, Node originalPoster) {

	return new BroadcastChannelMessage(header, network.myNode(), to, 
                message, channel, originalPoster);
    }

    /**
     * Make a new Exit channel message.
     *
     * @param to
     * @param channelName
     * @return
     */
    public ExitChannelMessage makeExitChannelMessage(
            Node to, String channelName) {

	return new ExitChannelMessage(header, network.myNode(), to,channelName);
    }

    /**
     * Make a new broadcast exit channel message.
     * 
     * @param to
     * @param channelName
     * @param exiter
     * @return
     */
    public BroadcastExitChannelMessage makeBroadcastExitChannelMessage(
            Node to, String channelName, Node exiter) {

        return new BroadcastExitChannelMessage(
                header, network.myNode(), to, channelName, exiter);
    }

    /**
     * Make a Close channel message.
     *
     * @param to
     * @param channelName
     * @return
     */
    public CloseChannelMessage makeCloseChannelMessage(Node to, String channelName) {
        return new CloseChannelMessage(header, network.myNode(), to,
                channelName);
    }
}
